package coupon

import (
	sqlc "bp/db/sqlc"
	"bp/internal/render"
	sharedVld "bp/internal/rpcserver/shared/vld"
	"bp/internal/service/entity/coupon"
	memberCoupon "bp/internal/service/entity/member_coupon"
	"bp/internal/util"
	couponGrpc "bp/rpc/gen/mwebapi/mcoupon"
	"context"
	"fmt"
	"time"
)

// VldGettingCouponReq 验证领取优惠券请求
func (s *CouponMWebApiImp) VldGettingCouponReq(ctx context.Context, q *sqlc.Queries, req *couponGrpc.GettingCouponReq) (
	ptr *memberCoupon.CreateMemberCouponParam,
	distributionID int64,
	err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	token := util.GetAuthorizationToken(ctx)

	if req.CouponId < 0 {
		err = render.InvalidArgumentRange("coupon_id")
		return
	}
	if !sharedVld.IsIssuer(req.GotIssuer) {
		err = render.InvalidArgumentValue("got_issuer")
		return
	}
	if !sharedVld.IsCouponDistributeScene(req.GotScene) {
		err = render.InvalidArgumentValue("got_scene")
		return
	}
	if req.GotSceneId < 0 {
		err = render.InvalidArgumentRange("got_scene_id")
		return
	}
	couponID := req.CouponId
	couponPtr, err := s.entityHub.CouponService.GetCouponPtr(ctx, q, couponID)
	if err != nil {
		return
	}
	// 检测优惠券状态
	if couponPtr.CouponStatus != string(sqlc.EmCouponStatusPublished) {
		err = fmt.Errorf("优惠券不可用")
		return
	}
	memberID := token.MemberID
	// slog.Infof("token:%+v", token)
	// slog.Infof("memberID:%d", memberID)

	// 检测领取人对该券是否达到最大领取数
	isReachMaximumGotFrequency, err := s.entityHub.MemberCouponService.CheckHasReachMaxiumGotFrequencyToMember(ctx, q, &memberCoupon.CheckHasReachMaxiumGotFrequencyToMemberParam{
		CouponPtr: couponPtr,
		MemberID:  memberID,
	})
	if err != nil {
		return
	}
	if isReachMaximumGotFrequency {
		err = fmt.Errorf("已达到最大领取数")
		return
	}

	gotIssuer := req.GotIssuer
	gotScene := req.GotScene
	// 检测是否有可用的coupon sn
	hasAnyCouponSnCanGot, err := s.entityHub.CouponService.CheckHasAnyCouponSnCanGot(ctx, q, &coupon.CheckHasAnyCouponSnCanGotParam{
		CouponPtr:       couponPtr,
		Issuer:          gotIssuer,
		DistributeScene: gotScene,
	})
	if err != nil {
		return
	}
	if !hasAnyCouponSnCanGot {
		err = fmt.Errorf("券已领完")
		return
	}

	var begined, ended time.Time
	location := time.Now().Location()
	if couponPtr.UsePeriodType == string(sqlc.EmCouponUsePeriodTypeSinceGot) {
		availableAfterGotDays := int(couponPtr.AvailableAfterGotDays.Int32)
		days := int(couponPtr.Days.Int32)
		now := time.Now()
		if availableAfterGotDays > 0 {
			begined = time.Date(now.Year(), now.Month(), now.Day()+availableAfterGotDays, 0, 0, 0, 0, location)
		} else {
			begined = now
		}
		ended = time.Date(now.Year(), now.Month(), now.Day()+availableAfterGotDays+days, 23, 59, 59, 0, location)
	} else if couponPtr.UsePeriodType == string(sqlc.EmCouponUsePeriodTypeFixedDate) {
		useBegined := couponPtr.UseBegined.Time
		useEnded := couponPtr.UseEnded.Time
		begined = time.Date(useBegined.Year(), useBegined.Month(), useBegined.Day(), 0, 0, 0, 0, useBegined.Location())
		ended = time.Date(useEnded.Year(), useEnded.Month(), useEnded.Day(), 23, 59, 59, 0, useEnded.Location())
	}

	sn, distributionID, err := s.entityHub.CouponService.GetAndUpdateCouponSnAvailable(ctx, q, &coupon.GetCouponSnAvailableParam{
		CouponID:        couponID,
		Issuer:          gotIssuer,
		DistributeScene: gotScene,
		MemberID:        memberID,
	})
	if err != nil {
		return
	}

	gotSceneId := req.GotSceneId
	// 当公开领取和扫码领取时场景id外部不传,所以从获取的CouponSn里获取
	if gotScene == string(sqlc.EmCouponDistributeScenePublicGet) || gotScene == string(sqlc.EmCouponDistributeSceneShareQrcode) {
		gotSceneId = distributionID
	}

	ptr = &memberCoupon.CreateMemberCouponParam{
		CreateMemberCouponParamsPtr: &sqlc.CreateMemberCouponParams{
			BrandID:        couponPtr.BrandID,
			MemberID:       memberID,
			CouponID:       couponID,
			Sn:             sn,
			GotIssuer:      gotIssuer,
			GotScene:       gotScene,
			GotSceneID:     gotSceneId,
			OwnerType:      couponPtr.OwnerType,
			OwnerID:        couponPtr.OwnerID,
			Name:           couponPtr.Name,
			Desc:           couponPtr.Desc,
			Tags:           couponPtr.Tags,
			Nature:         couponPtr.Nature,
			OfferCategory:  couponPtr.OfferCategory,
			OfferType:      couponPtr.OfferType,
			Bg:             couponPtr.Bg,
			Price:          couponPtr.Price,
			Quota:          couponPtr.Quota,
			OffMaximum:     couponPtr.OffMaximum,
			Begined:        begined,
			Ended:          ended,
			UseTimeRanges:  couponPtr.UseTimeRanges,
			DateChooseType: couponPtr.DateChooseType,
			Weekdays:       couponPtr.Weekdays,
			Monthdays:      couponPtr.Monthdays,
			UseScenes:      couponPtr.UseScenes,
		},
	}
	slog.Infof("coupon_imp/cmd_vld.VldGettingCouponReq ok")
	return
}
